package com.gph.saviorframework.security.web.controller;

import com.alibaba.fastjson.JSONArray;
import com.gph.saviorframework.Constants;
import com.gph.saviorframework.ErrorCode;
import com.gph.saviorframework.OaConstants;
import com.gph.saviorframework.SaviorFrameworkException;
import com.gph.saviorframework.common.model.PermissionType;
import com.gph.saviorframework.common.model.ResourcePermission;
import com.gph.saviorframework.common.model.User;
import com.gph.saviorframework.oa.model.ResourceDataType;
import com.gph.saviorframework.security.service.OrgService;
import com.gph.saviorframework.security.service.ResourcePermissionService;
import com.gph.saviorframework.security.service.UserService;
import com.gph.saviorframework.uitl.EnumConvertor;
import com.gph.saviorframework.uitl.SecurityUtils;
import com.gph.saviorframework.util.RequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * 数据权限控制器
 *
 * @author guopeihui
 */
@Controller
@RequestMapping("/" + Constants.FRAMEWORK_REQUEST_PATH + "/resource-permission")
@Slf4j
public class ResourcePermissionController {

    /** 领域对象名称 */
    private static final String domain = ResourcePermission.class.getSimpleName().toLowerCase();

    @Autowired
    private ResourcePermissionService resourcePermissionService;

    @Autowired
    private SecurityUtils securityUtils;

    @Autowired
    private OrgService orgService;

    @Autowired
    private UserService userService;

    @Autowired
    private MessageSourceAccessor messages;

    private final String viewPrefix = OaConstants.FRAMEWORK_REQUEST_PATH + "/" + OaConstants.MODULE_CATEGORY_SECURITY + "/" + domain + "/" + domain + "_";

    @RequestMapping(value = "/config", method = RequestMethod.GET)
    public String configPage() throws SaviorFrameworkException {
        return viewPrefix + "config";
    }

    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public String createPage() throws SaviorFrameworkException {
        return viewPrefix + "create";
    }

    /**
     * 为某个用户创建数据权限
     * @param permission
     * @param checkedOrgs
     * @return
     * @throws SaviorFrameworkException
     */
    @RequestMapping(value = "/saveOrUpdate/{username}", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap create(@ModelAttribute ResourcePermission permission,
                           @RequestParam(value = "checkedOrgs",required = false)String[] checkedOrgs,
                           @RequestParam(value = "checkedUsers",required = false)String[] checkedUsers,
                           @RequestParam(value = "expression",required = false)String[] expression,
                           @PathVariable(value = "username")String username) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();

        try {

            //如果存在就先删除以前的相关数据
            resourcePermissionService.deleteByResourceTypeAndUserId(username, permission.getResourceType());

            permission.setId(UUID.randomUUID().toString());
            permission.setUserId(username);
            if(permission.getPermissionType().equals(PermissionType.ORGS.name())){
                permission.setOrgIds(StringUtils.join(checkedOrgs, ","));

                List<String> userIds = new ArrayList<String>();
                //查询所有部门的人员编号
                for(String orgId : checkedOrgs){
                    userIds.addAll(userService.getUserIdsByOrgId(orgId));
                }
                permission.setUserIds(StringUtils.join(userIds, ","));
            }
            else if(permission.getPermissionType().equals(PermissionType.ALL.name())){
                permission.setOrgIds(StringUtils.join(orgService.getAllIds(),","));
                permission.setUserIds(StringUtils.join(userService.getIds(), ","));
            }

            if(permission.getPermissionType().equals(PermissionType.USERS.name())){
                permission.setUserIds(StringUtils.join(checkedUsers,","));
            }
            resourcePermissionService.save(permission);

            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            modelMap.addAttribute(OaConstants.DEFAULT_ID_KEY, permission.getId());
        }
        catch (Exception ex){
            ex.printStackTrace();
        }

        return modelMap;
    }

    @RequestMapping(value = "/org", method = RequestMethod.GET)
    @ResponseBody
    public void getOrgTree(HttpServletRequest request,HttpServletResponse response) throws SaviorFrameworkException, IOException {
        JSONArray array = new JSONArray();
        String id = request.getParameter("id");
        if(StringUtils.isEmpty(id)){
            id=securityUtils.getUser().getOrg().getId();
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("id", securityUtils.getUser().getOrg().getId());
            map.put("name", securityUtils.getUser().getOrg().getName());
            map.put("pId", null);
            map.put("pName", null);
            map.put("children", orgService.findByParent(id));
            array.add(map);
        }
        else{
            List<Map<String, Object>> list = orgService.findByParent(id);
            array = JSONArray.parseArray(JSONArray.toJSONString(list));
        }
        response.getWriter().write(array.toString());
    }

    @RequestMapping(value = "/org/{username}/{resourceType}", method = RequestMethod.GET)
    @ResponseBody
    public void getOrgTreeByUserName(HttpServletRequest request,HttpServletResponse response,
                                     @PathVariable(value = "username")String username,
                                     @PathVariable(value = "resourceType")String resourceType) throws SaviorFrameworkException, IOException {
        JSONArray array = new JSONArray();
        String id = request.getParameter("id");
        //根据用户名查找分配的部门
        ResourcePermission resourcePermission = resourcePermissionService.getByUserIdAndResourceType(username, resourceType);

        if(StringUtils.isEmpty(id)){
            id=securityUtils.getUser().getOrg().getId();
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("id", securityUtils.getUser().getOrg().getId());
            map.put("name", securityUtils.getUser().getOrg().getName());
            map.put("pId", null);
            map.put("pName", null);

            List<Map<String,Object>> children = orgService.findByParent(id);

            if(resourcePermission != null){
                //获取部门
                String orgIds = resourcePermission.getOrgIds();
                if(orgIds.contains(securityUtils.getUser().getOrg().getId())){
                    map.put("checked",true);
                }

                for(Map<String,Object> temp : children){
                    if(orgIds.contains(temp.get("id").toString())){
                        temp.put("checked", true);
                    }
                }
            }

            map.put("children",children);

            array.add(map);
        }
        else{
            List<Map<String, Object>> list = orgService.findByParent(id);
            if(resourcePermission != null){
                //获取部门
                String orgIds = resourcePermission.getOrgIds();
                for(Map<String,Object> temp : list){
                    if(orgIds.contains(temp.get("id").toString())){
                        temp.put("checked", true);
                    }
                }
            }
            array = JSONArray.parseArray(JSONArray.toJSONString(list));
        }
        response.getWriter().write(array.toString());
    }


    @RequestMapping(value = "/users/{username}/{resourceType}", method = RequestMethod.GET)
    @ResponseBody
    public void getUsersTreeByUserName(HttpServletRequest request,HttpServletResponse response,
                                       @PathVariable(value = "username")String username,
                                       @PathVariable(value = "resourceType")String resourceType) throws SaviorFrameworkException, IOException {
        JSONArray array = new JSONArray();
        String id = request.getParameter("id");
        ResourcePermission resourcePermission = resourcePermissionService.getByUserIdAndResourceType(username, resourceType);
        if(StringUtils.isEmpty(id)){
            id=securityUtils.getUser().getOrg().getId();
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("id", securityUtils.getUser().getOrg().getId());
            map.put("name", securityUtils.getUser().getOrg().getName());
            map.put("pId", null);
            map.put("pName", null);
            map.put("nocheck",true);

            //构造子节点，包括用户和下级部门
            //根据用户名查找分配的部门
            if(resourcePermission!=null){
                String userIds = resourcePermission.getUserIds();
                if(StringUtils.isNotEmpty(userIds)){
                    map.put("children", genOrgDataForZTree(id,userIds));
                }
            }
            else {
                map.put("children", genOrgDataForZTree(id));
            }

            array.add(map);
        }
        else{
            List<Map<String,Object>> list = null;
            if(resourcePermission!=null){
                String userIds = resourcePermission.getUserIds();
                if(StringUtils.isNotEmpty(userIds)){
                    list = genOrgDataForZTree(id,userIds);
                }
            }
            else {
                list = genOrgDataForZTree(id);
            }
            array = JSONArray.parseArray(JSONArray.toJSONString(list));
        }
        response.getWriter().write(array.toString());
    }

    @RequestMapping(value = "/users", method = RequestMethod.GET)
    @ResponseBody
    public void getUsersTree(HttpServletRequest request,HttpServletResponse response) throws SaviorFrameworkException, IOException {
        JSONArray array = new JSONArray();
        String id = request.getParameter("id");
        if(StringUtils.isEmpty(id)){
            id=securityUtils.getUser().getOrg().getId();
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("id", securityUtils.getUser().getOrg().getId());
            map.put("name", securityUtils.getUser().getOrg().getName());
            map.put("pId", null);
            map.put("pName", null);
            map.put("nocheck",true);

            //构造子节点，包括用户和下级部门
            map.put("children",genOrgDataForZTree(id));

            array.add(map);
        }
        else{
            List<Map<String,Object>> list = genOrgDataForZTree(id);
            array = JSONArray.parseArray(JSONArray.toJSONString(list));
        }
        response.getWriter().write(array.toString());
    }

    private List<Map<String,Object>> genOrgDataForZTree(String orgId){
        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();

        List<Map<String,Object>> orgChildren = orgService.findByParent(orgId);
        for(Map<String,Object> temp : orgChildren){
            temp.put("nocheck",true);
            temp.put("isParent",true);
        }
        list.addAll(orgChildren);

        List<User> users = userService.findByOrgId(orgId);
        //然后组织符合zTree的数据
        for(User user : users){
            Map<String,Object> userMap = new LinkedHashMap<String,Object>();
            userMap.put("id",user.getUsername());
            userMap.put("name",user.getName());
            userMap.put("pId",orgId);
            userMap.put("pName",orgService.get(orgId).getId());

            list.add(userMap);
        }

        return list;
    }

    private List<Map<String,Object>> genOrgDataForZTree(String orgId,String userIds){
        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();

        List<Map<String,Object>> orgChildren = orgService.findByParent(orgId);
        for(Map<String,Object> temp : orgChildren){
            temp.put("nocheck",true);
            temp.put("isParent",true);
        }
        list.addAll(orgChildren);

        List<User> users = userService.findByOrgId(orgId);
        //然后组织符合zTree的数据
        for(User user : users){
            Map<String,Object> userMap = new LinkedHashMap<String,Object>();
            userMap.put("id",user.getUsername());
            userMap.put("name",user.getName());
            userMap.put("pId",orgId);
            userMap.put("pName",orgService.get(orgId).getId());

            if(userIds.contains(user.getUsername())){
                userMap.put("checked",true);
            }

            list.add(userMap);
        }

        return list;
    }

    @RequestMapping(value = "/res-type", method = RequestMethod.GET)
    @ResponseBody
    public List<Map<String,String>> getResourceDataType(HttpServletRequest request,HttpServletResponse response) throws SaviorFrameworkException, IOException {
        return EnumConvertor.enum2ListMap(ResourceDataType.class);
    }

    @RequestMapping(value = "/permission-type", method = RequestMethod.GET)
    @ResponseBody
    public List<Map<String,String>> getPermissionType(HttpServletRequest request,HttpServletResponse response) throws SaviorFrameworkException, IOException {
        return EnumConvertor.enum2ListMap(PermissionType.class);
    }

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public String listPage(){
        return viewPrefix + "list";
    }

    /**
     * 获取数据权限列表
     */
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    @ResponseBody
    public String list(
            @RequestParam(value = OaConstants.DEFAULT_PAGE_MODEL_KEY, required = false, defaultValue = OaConstants.DEFAULT_PAGE_START) Integer start,
            @RequestParam(value = OaConstants.DEFAULT_RECORD_MODEL_KEY, required = false, defaultValue = OaConstants.DEFAULT_PAGE_SIZE) Integer limit,
            @RequestParam(value = OaConstants.DEFAULT_SORT_MODEL_KEY, required = false, defaultValue = OaConstants.DEFAULT_SORT_FIELD) String sort,
            @RequestParam(value = OaConstants.DEFAULT_DIR_MODEL_KEY, required = false, defaultValue = OaConstants.DEFAULT_SORT_DIRECTION) String dir,
            HttpServletRequest request) throws SaviorFrameworkException {
        String json = null;
        Map<String, Object> params = RequestUtil.getQueryMap(request, resourcePermissionService.getFields());
        try {
            Map<String, Object> map = resourcePermissionService.find(start,limit,sort,dir,params);
            List<Map<String,Object>> list = (List<Map<String,Object>>)map.get(Constants.DEFAULT_RECORD_MODEL_KEY);

            for (Map<String, Object> it : list) {
                String permissionType = it.get("permissionType").toString();
                String resourceType = it.get("resourceType").toString();

                it.put("resourceType", ResourceDataType.valueOf(resourceType).getName());
                it.put("permissionType", PermissionType.valueOf(permissionType).getName());
                it.put("resourceTypeId", resourceType);
                it.put("permissionTypeId", permissionType);
            }

            json = JSONArray.toJSONString(map);
            log.info(messages.getMessage("log.info.list", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain) }));
        }
        catch (DataAccessException e) {
            e.printStackTrace();
            log.error(messages.getMessage("log.error.list", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain) }));
        }
        return json;
    }

    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public String editPage(){
        return viewPrefix + "edit";
    }

    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap delete(@RequestParam(value = "ids", required = true) String[] ids) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            resourcePermissionService.deleteByIds(ids);
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            log.info(messages.getMessage("log.info.delete", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain),
                    org.springframework.util.StringUtils.arrayToDelimitedString((Object[]) ids, "|")}));
        } catch (DataIntegrityViolationException e) {
            e.printStackTrace();
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(OaConstants.DEFAULT_ERROR_KEY, ErrorCode.DATA_INTEGRITY_VIOLATION);
            log.error(messages.getMessage("log.error.delete", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain),
                    org.springframework.util.StringUtils.arrayToDelimitedString((Object[]) ids, "|") }));
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(OaConstants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(OaConstants.DEFAULT_ERROR_KEY, e.getMessage());
            log.error(messages.getMessage("log.error.delete", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain),
                    org.springframework.util.StringUtils.arrayToDelimitedString((Object[]) ids, "|")}));
        }
        return modelMap;
    }
}
